home *** CD-ROM | disk | FTP | other *** search
/ The Guided Tour of Multimedia (Second Edition) / The Guided Tour of Multimedia (Second Edition).iso / trials / director / evalcopy / director.z / FILEIO.C < prev    next >
C/C++ Source or Header  |  1994-06-02  |  41KB  |  1,374 lines

  1. /*****************************************************************************
  2.  
  3.                            Macromedia FileIO XObject
  4.                                        
  5.                          (c) Copyright 1993 Macromedia
  6.                               All Rights Reserved
  7.  
  8.     Revision History:
  9.  
  10.  24may94    JT    Fixed append. use full path name for mFileName
  11.        16feb93  PTM     Revised internal documentation
  12.         9feb93  JT      mReadPICT returns file name
  13.         9feb93  JT      Don't do any CR-LF conversion. Added mDosFileName
  14.  
  15.     !!@ fileio doc: cannot read or write more than 64K
  16.  
  17.  *****************************************************************************/
  18.  
  19. #include <windows.h>
  20. #include <stdio.h>      // For remove
  21. #include <stdlib.h>        // for _fullpath
  22. #include "XObject.h"
  23.  
  24.  
  25. /*
  26. ------------------------------------------------------------------------------
  27. Function Prototypes:
  28. ------------------------------------------------------------------------------
  29. */
  30.  
  31. short __far __pascal __export LibMain(
  32.     HANDLE hndInstance, WORD suDataSeg, WORD suHeapSize, LPSTR pCmdLine);
  33. int __export __far __pascal WEP(int nParameter);
  34.  
  35. long __far __pascal __export _FileIO_mNew(
  36.     LxMemHandle hOpenMode, LxMemHandle hNameOrType, 
  37.     LxProcTablePtr xtbl, LxMemHandle hFile);
  38. long __far __pascal __export _FileIO_mDispose(
  39.     LxProcTablePtr xtbl, LxMemHandle hFile);
  40. LxMemHandle __far __pascal __export _FileIO_mFileName(
  41.     LxProcTablePtr xtbl, LxMemHandle hFile);
  42. LxMemHandle __far __pascal __export _FileIO_mNativeFileName(
  43.     LxProcTablePtr xtbl, LxMemHandle hFile);
  44. long __far __pascal __export _FileIO_mStatus(
  45.     LxProcTablePtr xtbl, LxMemHandle hFile);
  46. LxMemHandle __far __pascal __export _FileIO_mError(
  47.     long lErrorCode, LxProcTablePtr xtbl, LxMemHandle hFile);
  48. long __far __pascal __export _FileIO_mSetPosition(
  49.     long lPos, LxProcTablePtr xtbl, LxMemHandle hFile);
  50. long __far __pascal __export _FileIO_mGetPosition(
  51.     LxProcTablePtr xtbl, LxMemHandle hFile);
  52. long __far __pascal __export _FileIO_mGetLength(
  53.     LxProcTablePtr xtbl, LxMemHandle hFile);
  54. long __far __pascal __export _FileIO_mWriteChar(
  55.     long lCharNum, LxProcTablePtr xtbl, LxMemHandle hFile);
  56. long __far __pascal __export _FileIO_mWriteString(
  57.     LxMemHandle hData, LxProcTablePtr xtbl, LxMemHandle hFile);
  58. long __far __pascal __export _FileIO_mReadChar(
  59.     LxProcTablePtr xtbl, LxMemHandle hFile);
  60. LxMemHandle __far __pascal __export _FileIO_mReadLine(
  61.     LxProcTablePtr xtbl, LxMemHandle hFile);
  62. LxMemHandle __far __pascal __export _FileIO_mReadFile(
  63.     LxProcTablePtr xtbl, LxMemHandle hFile);
  64. long __far __pascal __export _FileIO_mReadWord(
  65.     LxProcTablePtr xtbl, LxMemHandle hFile);
  66. long __far __pascal __export _FileIO_mReadToken(
  67.     LxMemHandle breakString, LxMemHandle skipString, 
  68.     LxProcTablePtr xtbl, LxMemHandle hFile);
  69. long __far __pascal __export _FileIO_mGetFinderInfo(
  70.     LxProcTablePtr xtbl, LxMemHandle hFile);
  71. long __far __pascal __export _FileIO_mDelete(
  72.     LxProcTablePtr xtbl, LxMemHandle hFile);
  73. long __far __pascal __export _FileIO_mReadPICT(
  74.     long nargs, LxValuePtr argp, LxProcTablePtr xtbl, LxMemHandle hFile);
  75.  
  76. long __far __pascal __export _FileIO_mSetOverrideDrive(
  77.     long driverLetter, LxProcTablePtr xtbl, LxMemHandle hFile);
  78.  
  79. /*
  80. ------------------------------------------------------------------------------
  81. Constants:
  82. ------------------------------------------------------------------------------
  83. */
  84.  
  85. // Maximum buffer size that _lread can handle
  86. #define MAX_LREAD_SIZE  (0xFFFE)
  87.  
  88. #define FILEIO_TAB      0x09
  89. #define FILEIO_LF       0x0A
  90. #define FILEIO_CR       0x0D
  91. #define FILEIO_EOF      0x26
  92. #define FILEIO_CRLF_STR "\r\n"
  93.  
  94. #define FILEIO_OPEN_CAPTION " "
  95. #define FILEIO_SAVE_CAPTION " "
  96. #define FILEIO_DEF_EXT  "*.txt"
  97. #define FILEIO_DEF_PATH "\\"
  98.  
  99. #define FILEIOE_SUCCESS         0
  100. #define FILEIOE_MEM_ALLOC       1
  101. #define FILEIOE_DIR_FULL        -33
  102. #define FILEIOE_VOL_FULL        -34
  103. #define FILEIOE_VOL_NOT_FOUND   -35
  104. #define FILEIOE_IO_FAILURE      -36
  105. #define FILEIOE_BAD_FILE_NAME   -37
  106. #define FILEIOE_FILE_NOT_OPEN   -38
  107. #define FILEIOE_TOO_MANY_OPEN   -42
  108. #define FILEIOE_FILE_NOT_FOUND  -43
  109. #define FILEIOE_NO_SUCH_DRIVE   -56
  110. #define FILEIOE_EMPTY_DRIVE     -65
  111. #define FILEIOE_DIR_NOT_FOUND   -120
  112.  
  113. /* following belong in WINDOWS.H (so there) */
  114.  
  115. #define OF_FROM_BEGIN   0
  116. #define OF_FROM_CURR    1
  117. #define OF_FROM_END     2
  118.  
  119. #define MAXSTRINGSIZE   255
  120.  
  121. /*
  122. ------------------------------------------------------------------------------
  123. Types:
  124. ------------------------------------------------------------------------------
  125. */
  126.  
  127. typedef struct
  128. {
  129.     LxXObjHeader    head;
  130.     LxMemHandle     hFileName;
  131.     short           sFileID;
  132.     short           sReadWrite;
  133. }   FileIO, FAR * pFileIO;
  134.  
  135. /*
  136. ------------------------------------------------------------------------------
  137. Variables:
  138. ------------------------------------------------------------------------------
  139. */
  140.  
  141. long    lFileIOError = 0;
  142. HANDLE  hInst;
  143.  
  144. /*
  145. ------------------------------------------------------------------------------
  146. FUNCTION        ||      LibMain()
  147.  
  148. Windows Entry Procedure for DLLs.  Called by LibEntry routine.
  149. ------------------------------------------------------------------------------
  150. */
  151.  
  152. short __far __pascal __export LibMain(
  153.     HANDLE hndInstance, WORD suDataSeg, WORD suHeapSize, LPSTR pCmdLine)
  154. {
  155.     if (suHeapSize != 0)
  156.     {
  157.         if (! LocalInit( (UINT)suDataSeg, (UINT)NULL, (UINT)suHeapSize))
  158.         {
  159.             return (0);
  160.         }
  161.     }
  162.     hInst = hndInstance;
  163.     return (1);
  164. }
  165.  
  166.  
  167.  
  168. //DJ20jul93/*
  169. //DJ20jul93------------------------------------------------------------------------------
  170. //DJ20jul93FUNCTION        ||      WEP()
  171. //DJ20jul93
  172. //DJ20jul93Windows Exit Procedure for DLLs.
  173. //DJ20jul93------------------------------------------------------------------------------
  174. //DJ20jul93*/
  175. //DJ20jul93int __export __far __pascal WEP(int nParameter)
  176. //DJ20jul93{
  177. //DJ20jul93    return 1;
  178. //DJ20jul93}
  179.  
  180.  
  181. /*
  182. ------------------------------------------------------------------------------
  183. Internal Functions:
  184. ------------------------------------------------------------------------------
  185. */
  186.  
  187. static BOOL GetOpenInfo(
  188.     pFileIO pFile, LPSTR pstrOpenMode, LPSTR pstrNameOrType, 
  189.     LxProcTablePtr xtbl);
  190. static LxMemHandle PromptOpenFile(
  191.     pFileIO pFile, LPSTR pstrType, LxProcTablePtr xtbl);
  192. static LxMemHandle PromptSaveFile(
  193.     pFileIO pFile, LPSTR pstrName, LxProcTablePtr xtbl);
  194. static BOOL OpenTheFile( pFileIO pFile, LxProcTablePtr xtbl);
  195.  
  196. /*
  197. ------------------------------------------------------------------------------
  198. Macros:
  199. ------------------------------------------------------------------------------
  200. */
  201.  
  202.  
  203. /*
  204. ------------------------------------------------------------------------------
  205. FUNCTION        ||      _FileIO_mNew
  206.  
  207. Open a file and return a file reference object for it.
  208.  
  209. Arguments:
  210.     hOpenMode       Option String (read,write,append,?read,?write,?append)
  211.     hNameOrType     Filename string or file type (e.g. "TXT")
  212.     xtbl            Callback proc table
  213.     hFile           LxMemHandle to object instance
  214. ------------------------------------------------------------------------------
  215. */
  216.  
  217. long __far __pascal __export _FileIO_mNew(
  218.     LxMemHandle hOpenMode, LxMemHandle hNameOrType, 
  219.     LxProcTablePtr xtbl, LxMemHandle hFile)
  220. {
  221.     pFileIO pFile;
  222.     LPSTR    pstrOpenMode;
  223.     LPSTR    pstrNameOrType;
  224.  
  225.     lFileIOError = FILEIOE_SUCCESS;
  226.     pstrOpenMode = xtbl->mem_Lock( hOpenMode);
  227.     pstrNameOrType = xtbl->mem_Lock( hNameOrType);
  228.  
  229.     if ( xtbl->mem_SetSize(hFile, (long) sizeof(FileIO) )  != NULL)
  230.     {
  231.         pFile = xtbl->mem_Lock( hFile);
  232.  
  233.         pFile->sFileID = -1;
  234.         pFile->hFileName = NULL;
  235.         pFile->sReadWrite = OF_READ;
  236.  
  237.         if (GetOpenInfo(pFile, pstrOpenMode, pstrNameOrType, xtbl))
  238.         {
  239.             OpenTheFile(pFile, xtbl);
  240.         }
  241.         if ((lFileIOError != FILEIOE_SUCCESS) && (pFile->hFileName != NULL))
  242.         {
  243.             xtbl->mem_Dispose(pFile->hFileName);
  244.         }
  245.         xtbl->mem_Unlock( hFile);
  246.     }
  247.     else
  248.     {
  249.         lFileIOError = FILEIOE_MEM_ALLOC;
  250.     }
  251.     xtbl->mem_Unlock( hNameOrType);
  252.     xtbl->mem_Unlock( hOpenMode);
  253.     return (lFileIOError);
  254. }
  255.  
  256. /*
  257. ------------------------------------------------------------------------------
  258. FUNCTION        ||      GetOpenInfo
  259.  
  260. Initializes object instance variables to reflect the open mode and filename.
  261. Called prior to actually opening the file.
  262.  
  263. Arguments:
  264.     pFileIO         Pointer to FileIO object instance
  265.     pstrOpenMode    Open mode string: read,write,append...
  266.     pstrNameOrType  Filename string, or type string (e.g. "TXT")
  267.     xtbl            Callback proc table
  268. ------------------------------------------------------------------------------
  269. */
  270.  
  271. static BOOL GetOpenInfo(
  272.     pFileIO pFile, LPSTR pstrOpenMode, LPSTR pstrNameOrType, 
  273.     LxProcTablePtr xtbl)
  274. {
  275.     char    strBuf[MAXSTRINGSIZE];
  276.         
  277.     if (lstrcmpi(pstrOpenMode, "read") == 0)
  278.     {
  279.         pFile->sReadWrite = OF_READ;
  280.         //xtbl->ConvertMACToDosPath( pstrNameOrType, strBuf, MAXSTRINGSIZE);
  281.         if (! _fullpath( strBuf, pstrNameOrType, MAXSTRINGSIZE))
  282.             lstrcpy( strBuf, pstrNameOrType); 
  283.         pFile->hFileName = xtbl->string_New(strBuf);
  284.     }
  285.     else if (lstrcmpi(pstrOpenMode, "?read") == 0)
  286.     {
  287.         pFile->sReadWrite = OF_READ;
  288.         pFile->hFileName = PromptOpenFile(pFile, pstrNameOrType, xtbl);
  289.     }
  290.     else if (lstrcmpi(pstrOpenMode, "write") == 0)
  291.     {
  292.         pFile->sReadWrite = OF_WRITE;
  293.         if (! _fullpath( strBuf, pstrNameOrType, MAXSTRINGSIZE))
  294.             lstrcpy( strBuf, pstrNameOrType); 
  295.         //xtbl->ConvertMACToDosPath( pstrNameOrType, strBuf, MAXSTRINGSIZE );
  296.         pFile->hFileName = xtbl->string_New(strBuf);
  297.     }
  298.     else if (lstrcmpi(pstrOpenMode, "?write") == 0)
  299.     {
  300.         pFile->sReadWrite = OF_WRITE;
  301.         xtbl->ConvertMACToDosPath( pstrNameOrType, strBuf, MAXSTRINGSIZE );
  302.         pFile->hFileName = PromptSaveFile(pFile, strBuf, xtbl);
  303.     }
  304.     else if (lstrcmpi(pstrOpenMode, "append") == 0)
  305.     {
  306.         pFile->sReadWrite = OF_READWRITE;
  307.         if (! _fullpath( strBuf, pstrNameOrType, MAXSTRINGSIZE))
  308.             lstrcpy( strBuf, pstrNameOrType); 
  309.         //xtbl->ConvertMACToDosPath( pstrNameOrType, strBuf, MAXSTRINGSIZE );
  310.         pFile->hFileName = xtbl->string_New(strBuf);
  311.     }
  312.     else if (lstrcmpi(pstrOpenMode, "?append") == 0)
  313.     {
  314.         pFile->sReadWrite = OF_READWRITE;
  315.         pFile->hFileName = PromptOpenFile(pFile, pstrNameOrType, xtbl);
  316.     }
  317.     else
  318.     {
  319.         lFileIOError = FILEIOE_BAD_FILE_NAME;
  320.     }
  321.     return (lFileIOError == FILEIOE_SUCCESS);
  322. }
  323.  
  324. /*
  325. ------------------------------------------------------------------------------
  326. FUNCTION        ||      PromptOpenFile
  327.  
  328. Displays "Open" dialog box to prompt for existing filename.
  329.  
  330. Arguments:
  331.     pFileIO         Pointer to FileIO object instance
  332.     pstrType        Filename extension string (e.g., "TXT" for *.TXT file)
  333.     xtbl            Callback proc table
  334. ------------------------------------------------------------------------------
  335. */
  336.  
  337. static LxMemHandle PromptOpenFile(
  338.     pFileIO pFile, LPSTR pstrType, LxProcTablePtr xtbl)
  339. {
  340.     char    astrDefSpec[128];
  341.     char    astrFileName[128];
  342.     BOOL    ok;
  343.         
  344.     if (*pstrType != 0)
  345.     {
  346.         lstrcpy(astrDefSpec, "*.");
  347.         lstrcat(astrDefSpec, pstrType);
  348.         astrDefSpec[5] = 0;     // Truncate spec to 3 chars + 2 for "*."
  349.     }
  350.     else
  351.     {
  352.         lstrcpy(astrDefSpec, "*.*");
  353.     }
  354.  
  355.     astrFileName[0] = 0;
  356.     ok = xtbl->fileDlg_Open( FILEIO_OPEN_CAPTION, astrDefSpec, astrFileName );
  357.     if (! ok)
  358.     {
  359.         lFileIOError = FILEIOE_FILE_NOT_FOUND;
  360.     }
  361.     return (xtbl->string_New(astrFileName));
  362. }
  363.  
  364. /*
  365. ------------------------------------------------------------------------------
  366. FUNCTION        ||      PromptSaveFile
  367.  
  368. Displays "Save As" dialog box to prompt for output filename.
  369.  
  370. Arguments:
  371.     pFileIO         Pointer to FileIO object instance
  372.     pstrType        Filename extension string (e.g., "TXT" for *.TXT file)
  373.     xtbl            Callback proc table
  374. ------------------------------------------------------------------------------
  375. */
  376.  
  377. static LxMemHandle PromptSaveFile(
  378.     pFileIO pFile, LPSTR pstrName, LxProcTablePtr xtbl)
  379. {
  380.     BOOL    ok;
  381.     char    astrFileName[MAXSTRINGSIZE];
  382.         
  383.     lstrcpy(astrFileName, pstrName);
  384.  
  385.     ok = xtbl->fileDlg_SaveAs( FILEIO_SAVE_CAPTION, 
  386.                                FILEIO_DEF_EXT, astrFileName );
  387.     if (! ok)
  388.     {
  389.         lFileIOError = FILEIOE_FILE_NOT_FOUND;
  390.     }
  391.     return xtbl->string_New( astrFileName );
  392. }
  393.  
  394. /*
  395. ------------------------------------------------------------------------------
  396. FUNCTION        ||      OpenTheFile
  397.  
  398. Creates or Opens the requested file, as specified by the hFileName
  399. and sReadWrite instance variables of pFileIO.  Sets sFileID to the
  400. newly opened file.  Returns TRUE if successful.
  401.  
  402. Arguments:
  403.     pFileIO         Pointer to FileIO object instance
  404.     xtbl            Callback proc table
  405. ------------------------------------------------------------------------------
  406. */
  407.  
  408. static BOOL OpenTheFile(pFileIO pFile, LxProcTablePtr xtbl)
  409. {
  410.     LPSTR    pstrName;
  411.  
  412.     pstrName = xtbl->mem_Lock( pFile->hFileName);
  413.  
  414.     switch (pFile->sReadWrite)
  415.     {
  416.     case OF_READ:
  417.         pFile->sFileID = _lopen(pstrName, pFile->sReadWrite);
  418.         break;
  419.  
  420.     case OF_WRITE:
  421.         pFile->sFileID = _lcreat(pstrName, 0);  /* 0 = normal attrs */
  422.  
  423.         /*
  424.          * If we weren't able to create (or truncate) the file, it must
  425.          * already exist, but be inaccessible. Try opening it as a hidden
  426.          * file. If that fails, try opening it as a system file. If that
  427.          * fails, the this is really and truly an error!
  428.          */
  429.  
  430.         if (pFile->sFileID == -1)
  431.             pFile->sFileID = _lcreat(pstrName, 2);  /* 2 = hidden */
  432.         if (pFile->sFileID == -1)
  433.             pFile->sFileID = _lcreat(pstrName, 3);  /* 3 = system */
  434.         break;
  435.  
  436.     case OF_READWRITE:
  437.         pFile->sFileID = _lopen(pstrName, pFile->sReadWrite);
  438.         if (pFile->sFileID == -1)
  439.         {
  440.             /*
  441.              * Failed to open an existing file, so create a new one!
  442.              */
  443.             pFile->sFileID = _lcreat(pstrName, 0);
  444.         }
  445.         else
  446.         {
  447.             /*
  448.              * Got an existing file, so fast-forward to the end.
  449.              */
  450.             _llseek(pFile->sFileID, 0L, OF_FROM_END);   /* go to EOF */
  451.         }
  452.         break;
  453.     }
  454.  
  455.     if (pFile->sFileID == -1)
  456.     {
  457.         //DJ07may93
  458.         // This used to return "I/O error" all the time.  Now it returns
  459.         // "file not found" if the file was being opened for read, and
  460.         // "I/O error" if the file is being created (and fails).
  461.         if (pFile->sReadWrite == OF_READ)
  462.             lFileIOError = FILEIOE_FILE_NOT_FOUND;
  463.         else
  464.             lFileIOError = FILEIOE_IO_FAILURE;
  465.     }
  466.  
  467.     xtbl->mem_Unlock( pFile->hFileName);
  468.     return (lFileIOError == FILEIOE_SUCCESS);
  469. }
  470.  
  471. /*
  472. ------------------------------------------------------------------------------
  473. FUNCTION        ||      _FileIO_mDispose
  474.  
  475. Dispose of a FileIO object instance.  Note: This method does not close or
  476. delete any open files.  
  477.  
  478. Arguments:
  479.     xtbl            Callback proc table
  480.     hFile           LxMemHandle to object instance
  481. ------------------------------------------------------------------------------
  482. */
  483.  
  484. long __far __pascal __export _FileIO_mDispose(
  485.     LxProcTablePtr xtbl, LxMemHandle hFile)
  486. {
  487.     pFileIO pFile;
  488.  
  489.     lFileIOError = FILEIOE_SUCCESS;
  490.     pFile =  xtbl->mem_Lock( hFile);
  491.  
  492.     if (_lclose(pFile->sFileID) != 0)
  493.     {
  494.         lFileIOError = FILEIOE_FILE_NOT_OPEN;
  495.     }
  496.     if (pFile->hFileName != NULL)
  497.     {
  498.         xtbl->mem_Dispose(pFile->hFileName);
  499.     }
  500.  
  501.     xtbl->mem_Unlock( hFile);
  502.     xtbl->xobj_Dispose( hFile );
  503.         
  504.     return (lFileIOError);
  505. }
  506.  
  507. /*
  508. ------------------------------------------------------------------------------
  509. FUNCTION        ||      _FileIO_mFileName
  510.  
  511. Return the filename string of the open file.  Note that a Macintosh-style
  512. path expression is returned.
  513.  
  514. Arguments:
  515.     xtbl            Callback proc table
  516.     hFile           LxMemHandle to object instance
  517. ------------------------------------------------------------------------------
  518. */
  519.  
  520. LxMemHandle __far __pascal __export _FileIO_mFileName(
  521.     LxProcTablePtr xtbl, LxMemHandle hFile)
  522. {
  523.     pFileIO     pFile;
  524.     LxMemHandle  hName;
  525.  
  526.     lFileIOError = FILEIOE_SUCCESS;
  527.     pFile = xtbl->mem_Lock( hFile);
  528.  
  529.     hName = xtbl->mem_Clone(pFile->hFileName);
  530.     if (hName != NULL)
  531.     {
  532.         xtbl->ConvertDosPathToMAC( (LPSTR)*hName );
  533.     }
  534.                 
  535.     xtbl->mem_Unlock( hFile);
  536.  
  537.     return (hName);
  538. }
  539. /*
  540. ------------------------------------------------------------------------------
  541. FUNCTION        ||      _FileIO_mNativeFileName
  542.  
  543. Return the "native" filename string of the open file.  Note that a DOS-style
  544. path expression is returned.
  545.  
  546. Arguments:
  547.     xtbl            Callback proc table
  548.     hFile           LxMemHandle to object instance
  549. ------------------------------------------------------------------------------
  550. */
  551.  
  552. LxMemHandle __far __pascal __export _FileIO_mNativeFileName(
  553.     LxProcTablePtr xtbl, LxMemHandle hFile)
  554. {
  555.     pFileIO     pFile;
  556.     LxMemHandle  hName;
  557.  
  558.     lFileIOError = FILEIOE_SUCCESS;
  559.     pFile = xtbl->mem_Lock( hFile);
  560.  
  561.     hName = xtbl->mem_Clone(pFile->hFileName);
  562.                 
  563.     xtbl->mem_Unlock( hFile);
  564.         
  565.     return (hName);
  566. }
  567.  
  568. /*
  569. ------------------------------------------------------------------------------
  570. FUNCTION        ||      _FileIO_mStatus
  571.  
  572. Return the error status code of the last FileIO method call.
  573.  
  574. Arguments:
  575.     xtbl            Callback proc table
  576.     hFile           LxMemHandle to object instance
  577. ------------------------------------------------------------------------------
  578. */
  579.  
  580. long __far __pascal __export _FileIO_mStatus(
  581.     LxProcTablePtr xtbl, LxMemHandle hFile)
  582. {
  583.     return (lFileIOError);
  584. }
  585.  
  586. /*
  587. ------------------------------------------------------------------------------
  588. FUNCTION        ||      _FileIO_mError
  589.  
  590. Return the error string corresponding to the lErrorCode paramter passed.
  591.  
  592. Arguments:
  593.     lErrorCode      Error code returned by mStatus method
  594.     xtbl            Callback proc table
  595.     hFile           LxMemHandle to object instance
  596. ------------------------------------------------------------------------------
  597. */
  598.  
  599. LxMemHandle __far __pascal __export _FileIO_mError(
  600.     long lErrorCode, LxProcTablePtr xtbl, LxMemHandle hFile)
  601. {
  602.     LPSTR    pstrMsg;
  603.  
  604.     switch ((short) lErrorCode)
  605.     {
  606.     case FILEIOE_SUCCESS:
  607.         pstrMsg = "";
  608.         break;
  609.     case FILEIOE_MEM_ALLOC:
  610.         pstrMsg = "Memory allocation failure";
  611.         break;
  612.     case FILEIOE_DIR_FULL:
  613.         pstrMsg = "File directory full";
  614.         break;
  615.     case FILEIOE_VOL_FULL:
  616.         pstrMsg = "Volume full";
  617.         break;
  618.     case FILEIOE_VOL_NOT_FOUND:
  619.         pstrMsg = "Volume not found";
  620.         break;
  621.     case FILEIOE_IO_FAILURE:
  622.         pstrMsg = "I/O Error";
  623.         break;
  624.     case FILEIOE_BAD_FILE_NAME:
  625.         pstrMsg = "Bad file name";
  626.         break;
  627.     case FILEIOE_FILE_NOT_OPEN:
  628.         pstrMsg = "File not open";
  629.         break;
  630.     case FILEIOE_TOO_MANY_OPEN:
  631.         pstrMsg = "Too many files open";
  632.         break;
  633.     case FILEIOE_FILE_NOT_FOUND:
  634.         pstrMsg = "File not found";
  635.         break;
  636.     case FILEIOE_NO_SUCH_DRIVE:
  637.         pstrMsg = "No such drive";
  638.         break;
  639.     case FILEIOE_EMPTY_DRIVE:
  640.         pstrMsg = "No disk in drive";
  641.         break;
  642.     case FILEIOE_DIR_NOT_FOUND:
  643.         pstrMsg = "Directory not found";
  644.         break;
  645.     default:
  646.         pstrMsg = "Unknown error";
  647.         break;
  648.     }
  649.     return (xtbl->string_New(pstrMsg));
  650. }
  651.  
  652. /*
  653. ------------------------------------------------------------------------------
  654. FUNCTION        ||      _FileIO_mSetPosition
  655.  
  656. Set the file position to the value passed in lPos.
  657.  
  658. Arguments:
  659.     lPos            Byte offset within the file
  660.     xtbl            Callback proc table
  661.     hFile           LxMemHandle to object instance
  662. ------------------------------------------------------------------------------
  663. */
  664.  
  665. long __far __pascal __export _FileIO_mSetPosition(
  666.     long lPos, LxProcTablePtr xtbl, LxMemHandle hFile)
  667. {
  668.     pFileIO pFile;
  669.  
  670.     lFileIOError = FILEIOE_SUCCESS;
  671.     pFile = xtbl->mem_Lock( hFile);
  672.  
  673.     if (_llseek(pFile->sFileID, lPos, OF_FROM_BEGIN) == -1)
  674.     {
  675.         lFileIOError = FILEIOE_FILE_NOT_OPEN;
  676.     }
  677.     xtbl->mem_Unlock( hFile);
  678.     return (lFileIOError);
  679. }
  680.  
  681. /*
  682. ------------------------------------------------------------------------------
  683. FUNCTION        ||      _FileIO_mGetPosition
  684.  
  685. Return the current file position
  686.  
  687. Arguments:
  688.     xtbl            Callback proc table
  689.     hFile           LxMemHandle to object instance
  690. ------------------------------------------------------------------------------
  691. */
  692.  
  693. long __far __pascal __export _FileIO_mGetPosition(
  694.     LxProcTablePtr xtbl, LxMemHandle hFile)
  695. {
  696.     pFileIO pFile;
  697.     long    lPos;
  698.  
  699.     lFileIOError = FILEIOE_SUCCESS;
  700.     pFile = xtbl->mem_Lock( hFile);
  701.  
  702.     if ((lPos = _llseek(pFile->sFileID, 0L, OF_FROM_CURR)) == -1)
  703.     {
  704.         lFileIOError = FILEIOE_FILE_NOT_OPEN;
  705.     }
  706.     xtbl->mem_Unlock( hFile);
  707.     return (lPos);
  708. }
  709.  
  710. /*
  711. ------------------------------------------------------------------------------
  712. FUNCTION        ||      _FileIO_mGetLength
  713.  
  714. Return the size of the file (in bytes).
  715.  
  716. Arguments:
  717.     xtbl            Callback proc table
  718.     hFile           LxMemHandle to object instance
  719. ------------------------------------------------------------------------------
  720. */
  721.  
  722. long __far __pascal __export _FileIO_mGetLength(
  723.     LxProcTablePtr xtbl, LxMemHandle hFile)
  724. {
  725.     pFileIO pFile;
  726.     long    lPos;
  727.     long    lLength;
  728.  
  729.     lFileIOError = FILEIOE_SUCCESS;
  730.     pFile = xtbl->mem_Lock( hFile);
  731.  
  732.     if ((lPos = _llseek(pFile->sFileID, 0L, OF_FROM_CURR)) == -1)
  733.     {
  734.         lFileIOError = FILEIOE_FILE_NOT_OPEN;
  735.     }
  736.     else
  737.     {
  738.         lLength = _llseek(pFile->sFileID, 0L, OF_FROM_END);
  739.         _llseek(pFile->sFileID, lPos, OF_FROM_BEGIN);
  740.     }
  741.     xtbl->mem_Unlock( hFile);
  742.     return (lLength);
  743. }
  744.  
  745. /*
  746. ------------------------------------------------------------------------------
  747. FUNCTION        ||      _FileIO_mWriteChar
  748.  
  749. Write a single character (given by its ASCII code) to the file.
  750.  
  751. Arguments:
  752.     lCharNum        Input character (ASCII code)
  753.     xtbl            Callback proc table
  754.     hFile           LxMemHandle to object instance
  755. ------------------------------------------------------------------------------
  756. */
  757.  
  758. long __far __pascal __export _FileIO_mWriteChar(
  759.     long lCharNum, LxProcTablePtr xtbl, LxMemHandle hFile)
  760. {
  761.     pFileIO pFile;
  762.     BYTE     strChar;
  763.  
  764.     lFileIOError = FILEIOE_SUCCESS;
  765.     pFile = xtbl->mem_Lock( hFile);
  766.  
  767.     strChar = (BYTE) lCharNum;
  768.  
  769.     if (_lwrite(pFile->sFileID, &strChar, 1) != 1)
  770.     {
  771.         lFileIOError = FILEIOE_IO_FAILURE;
  772.     }
  773.     xtbl->mem_Unlock( hFile);
  774.     return (lFileIOError);
  775. }
  776.  
  777. /*
  778. ------------------------------------------------------------------------------
  779. FUNCTION        ||      _FileIO_mWriteString
  780.  
  781. Write a null-terminated string to the file.
  782.  
  783. Arguments:
  784.     lData           LxMemHandel to string data
  785.     xtbl            Callback proc table
  786.     hFile           LxMemHandle to object instance
  787. ------------------------------------------------------------------------------
  788. */
  789.  
  790. long __far __pascal __export _FileIO_mWriteString(
  791.     LxMemHandle hData, LxProcTablePtr xtbl, LxMemHandle hFile)
  792. {
  793.     pFileIO pFile;
  794.     LPSTR   pstrData;
  795.     UINT    len;
  796.         
  797.     lFileIOError = FILEIOE_SUCCESS;
  798.     pFile = xtbl->mem_Lock( hFile);
  799.     pstrData = xtbl->mem_Lock( hData);
  800.     len = (UINT) lstrlen( pstrData );
  801.         
  802.     if (_lwrite(pFile->sFileID, pstrData, len) != (UINT)len)
  803.     {
  804.         lFileIOError = FILEIOE_IO_FAILURE;
  805.     }
  806.  
  807.     xtbl->mem_Unlock( hData);
  808.     xtbl->mem_Unlock( hFile);
  809.     return (lFileIOError);
  810. }
  811.  
  812. /*
  813. ------------------------------------------------------------------------------
  814. FUNCTION        ||      _FileIO_mReadChar
  815.  
  816. Read the next character of the file and return it as an ASCII code value.
  817.  
  818. Arguments:
  819.     xtbl            Callback proc table
  820.     hFile           LxMemHandle to object instance
  821. ------------------------------------------------------------------------------
  822. */
  823.  
  824. long __far __pascal __export _FileIO_mReadChar(
  825.     LxProcTablePtr xtbl, LxMemHandle hFile)
  826. {
  827.     pFileIO pFile;
  828.     BYTE    strChar;
  829.     long    lCharNum;
  830.     short   sReadCount;
  831.  
  832.     lFileIOError = FILEIOE_SUCCESS;
  833.     pFile = xtbl->mem_Lock( hFile);
  834.  
  835.     sReadCount = _lread(pFile->sFileID, &strChar, 1);
  836.     if (sReadCount < 0)
  837.     {
  838.         lFileIOError = FILEIOE_IO_FAILURE;
  839.         lCharNum = -1;
  840.     }
  841.     else if (sReadCount == 1)
  842.     {
  843.         lCharNum = strChar;
  844.     }
  845.     xtbl->mem_Unlock( hFile);
  846.     return (lCharNum);
  847. }
  848.  
  849. /*
  850. ------------------------------------------------------------------------------
  851. FUNCTION        ||      _FileIO_mReadLine
  852.  
  853. Read the next line of the file (up to and including the next RETURN character)
  854. and return it as a string.
  855.  
  856. Arguments:
  857.     xtbl            Callback proc table
  858.     hFile           LxMemHandle to object instance
  859. ------------------------------------------------------------------------------
  860. */
  861.  
  862. LxMemHandle __far __pascal __export _FileIO_mReadLine(
  863.     LxProcTablePtr xtbl, LxMemHandle hFile)
  864. {
  865.     pFileIO     pFile;
  866.     short       sReadCount;
  867.     BYTE        strChar = 0;
  868.     BYTE        astrBuf[129];
  869.     short       sBufCount = 0;
  870.     LxMemHandle hLine = NULL;
  871.  
  872.     lFileIOError = FILEIOE_SUCCESS;
  873.     pFile = xtbl->mem_Lock ( hFile );
  874.  
  875.     hLine = xtbl->mem_New( 0, FALSE );
  876.     while (strChar != FILEIO_CR)
  877.     {
  878.         if ((sReadCount = _lread(pFile->sFileID, &strChar, 1)) < 1)
  879.         {
  880.             if (sReadCount != 0)
  881.             {
  882.                 lFileIOError = FILEIOE_IO_FAILURE;
  883.             }
  884.             break;
  885.         }
  886.         if (sBufCount >= sizeof(astrBuf) - 1)
  887.         {
  888.             if (! xtbl->mem_AppendPtr(hLine, astrBuf, sBufCount))
  889.             {
  890.                 break;
  891.             }
  892.             sBufCount = 0;
  893.         }
  894.         astrBuf[sBufCount++] = strChar;
  895.     }
  896.     astrBuf[sBufCount++] = 0;
  897.     xtbl->mem_AppendPtr( hLine, astrBuf, sBufCount );
  898.  
  899.     xtbl->mem_Unlock( hFile);
  900.     return (hLine);
  901. }
  902.  
  903. /*
  904. ------------------------------------------------------------------------------
  905. FUNCTION        ||      _FileIO_mReadFile
  906.  
  907. Read from the current file position through the end of the file
  908. and return the data read as a string.
  909.  
  910. Arguments:
  911.     xtbl            Callback proc table
  912.     hFile           LxMemHandle to object instance
  913. ------------------------------------------------------------------------------
  914. */
  915.  
  916. LxMemHandle __far __pascal __export _FileIO_mReadFile(
  917.     LxProcTablePtr xtbl, LxMemHandle hFile)
  918. {
  919.     pFileIO     pFile;
  920.     long        lCount;
  921.     long        lPos, lEof;
  922.     LxMemHandle hData;
  923.     LPSTR       pbData;
  924.  
  925.     lFileIOError = FILEIOE_SUCCESS;
  926.     pFile = xtbl->mem_Lock( hFile);
  927.  
  928.     // Determine size of file, begining from current position.
  929.     lPos = _llseek(pFile->sFileID, 0L, OF_FROM_CURR);
  930.     lEof = _llseek(pFile->sFileID, 0L, OF_FROM_END);
  931.     _llseek(pFile->sFileID, lPos, OF_FROM_BEGIN);
  932.  
  933.     lCount = lEof - lPos;
  934.     if (lCount > MAX_LREAD_SIZE)
  935.         lCount = MAX_LREAD_SIZE;
  936.  
  937.     if ((lPos < 0) || (lEof < 0))
  938.     {
  939.         lFileIOError = FILEIOE_FILE_NOT_OPEN;
  940.         hData = xtbl->string_New( "" );
  941.         goto home;
  942.     }
  943.     if (lCount <= 0)            /* normal EOF */
  944.     {
  945.         xtbl->mem_Unlock( hFile);
  946.         return xtbl->string_New( "" );
  947.     }
  948.     if ((hData = xtbl->mem_New( lCount + 1, FALSE)) == NULL)
  949.     {
  950.         /* -- No memory for string. -- */
  951.         lFileIOError = FILEIOE_MEM_ALLOC;
  952.         hData = 0;
  953.         goto home;
  954.     }
  955.     pbData = xtbl->mem_Lock( hData);
  956.  
  957.     if (_lread(pFile->sFileID, pbData, (UINT)lCount) != (UINT)lCount)
  958.     {
  959.         /* -- Read failed. Deallocated and return null string -- */
  960.         lFileIOError = FILEIOE_IO_FAILURE;
  961.         xtbl->mem_Unlock( hData);
  962.         xtbl->mem_Dispose ( hData );
  963.         hData = xtbl->string_New( "" );
  964.         goto home;
  965.     }
  966.     xtbl->mem_Unlock( hData);
  967.  
  968. home:
  969.     xtbl->mem_Unlock( hFile);
  970.     return (hData);
  971. }
  972.  
  973. #define BUFFSIZ 512
  974. enum searchmode  {skipping,saving,done};
  975.  
  976. /*
  977. ------------------------------------------------------------------------------
  978. FUNCTION        ||      Read1Char
  979.  
  980. Read next character from file.
  981. ------------------------------------------------------------------------------
  982. */
  983.  
  984. static char Read1Char(short sFileID, enum searchmode *searching)
  985. {
  986.     char cbuf;
  987.     long count = 1;
  988.  
  989.     if (_lread(sFileID, &cbuf, (UINT)count) != (UINT)count)
  990.     {
  991.         /* -- EOF read -- */
  992.         *searching += 1;
  993.     }
  994.                 
  995.     return (cbuf);
  996. }
  997.  
  998. /*
  999. ------------------------------------------------------------------------------
  1000. FUNCTION        ||      SkipReadBreak
  1001.  
  1002. Create a string from file stream. Skip over chars in argument "skips"
  1003. and stop at any character in argument "breaks."
  1004. Code taken from MAC FileIO. ie. I know it's ugly.
  1005. ------------------------------------------------------------------------------
  1006. */
  1007.  
  1008. static LxMemHandle SkipReadBreak(
  1009.     short sFileID, char *breaks, char *skips, LxProcTablePtr xtbl)
  1010. {
  1011.     LxMemHandle     strHdl;
  1012.     char            buff[BUFFSIZ];
  1013.     short           len = 0;
  1014.     long            hLen = 0;
  1015.     register char   *cp,newChar,cmpChar;
  1016.     enum searchmode searching;
  1017.     short           pushit;
  1018.     long            newPos;
  1019.  
  1020.     if (skips[0])
  1021.     {
  1022.         pushit = TRUE;
  1023.         searching = skipping;   /* if something to skip start skipping */
  1024.     }
  1025.     else
  1026.     {
  1027.         pushit = FALSE;
  1028.         searching = saving;     /* start saving - no skips */
  1029.     }
  1030.  
  1031.     strHdl = xtbl->mem_New(1, TRUE/*-zeroInit-*/);
  1032.  
  1033.     /* prime the pumps */
  1034.     newChar = Read1Char(sFileID, &searching);
  1035.  
  1036.     if (searching == skipping)  /* first skip white space chars */
  1037.     {
  1038.         cp = skips;
  1039.         while (cmpChar = *cp++) /* search for skip char */
  1040.         {
  1041.             if (cmpChar == newChar)     /* should we eat it?? */
  1042.             {
  1043.                 /* eat it - less calories, more filling! */
  1044.                 newChar = Read1Char(sFileID,&searching);
  1045.                 /* look for more yummy white space */
  1046.                 cp = skips;
  1047.             }
  1048.         }
  1049.         ++searching;
  1050.     }
  1051.  
  1052.     while (searching == saving) /* save while looking for break char */
  1053.     {
  1054.         buff[len++] = newChar;  /* Save the char into the buffer */
  1055.         if (len>=BUFFSIZ)       /* time to write into handle */
  1056.         {
  1057.             hLen = xtbl->mem_GetSize(strHdl);
  1058.             if (! xtbl->mem_SetSize(strHdl, hLen + BUFFSIZ) )
  1059.                 goto fail;
  1060.  
  1061.             //DJ01jun93--Fixed bug--Dest and source were reversed!
  1062.             // Append bytes collected from fixed-size buff into the string.
  1063.             xtbl->mem_Copy((char *)(*strHdl)+ (hLen-1), buff, BUFFSIZ);
  1064.             len = 0;
  1065.         }
  1066.  
  1067.         cp = breaks;
  1068.         while (cmpChar = *cp++) /* search for break char */
  1069.         {
  1070.             if (cmpChar == newChar)     /* got it - we're done */
  1071.             {
  1072.                 ++searching;
  1073.                 goto done;
  1074.             }
  1075.         }
  1076.         newChar = Read1Char(sFileID, &searching);       /* read next char */
  1077.     }
  1078.  
  1079. done:
  1080.     /* push back the break character if not a singleton */
  1081.     hLen = xtbl->mem_GetSize(strHdl);
  1082.     if (pushit && (len+hLen > 1))
  1083.     {
  1084.         if ((newPos = _llseek(sFileID, 0L, OF_FROM_CURR)) != -1)
  1085.         {
  1086.             --newPos;
  1087.             if (_llseek(sFileID, newPos, OF_FROM_BEGIN) != -1)
  1088.             {
  1089.                 if (hLen+len > 1)
  1090.                 --len;
  1091.             }
  1092.         }
  1093.     }
  1094.  
  1095.     /* return the buff and the handle combined as a string */
  1096.     if (! xtbl->mem_SetSize(strHdl, hLen + len) )
  1097.         goto fail;
  1098.     xtbl->mem_Copy( (char *)(*strHdl) + (hLen-1), buff, len);
  1099.     (*(char **)strHdl)[hLen + len-1] = 0;       /* zap last byte */
  1100.     return strHdl;
  1101.  
  1102. fail:
  1103.     xtbl->mem_Dispose( strHdl );
  1104.     return 0;
  1105. }
  1106.  
  1107. /*
  1108. ------------------------------------------------------------------------------
  1109. FUNCTION        ||      _FileIO_mReadWord
  1110.  
  1111. Read the word of the file and return it as a string.
  1112.  
  1113. Arguments:
  1114.     xtbl            Callback proc table
  1115.     hFile           LxMemHandle to object instance
  1116. ------------------------------------------------------------------------------
  1117. */
  1118.  
  1119. long __far __pascal __export _FileIO_mReadWord(
  1120.     LxProcTablePtr xtbl, LxMemHandle hFile)
  1121. {
  1122.     pFileIO     pFile;
  1123.     LxMemHandle hdl;
  1124.         
  1125.     lFileIOError = FILEIOE_SUCCESS;
  1126.         
  1127.     pFile = xtbl->mem_Lock( hFile);
  1128.         
  1129.     hdl = SkipReadBreak( pFile->sFileID, " \r"/*-break-*/, 
  1130.                                          " "/*-skip-*/, xtbl );
  1131.     xtbl->mem_Unlock( hFile);
  1132.     return (long)hdl;
  1133. }
  1134.  
  1135.  
  1136. /*
  1137. ------------------------------------------------------------------------------
  1138. FUNCTION        ||      _FileIO_mReadToken
  1139.  
  1140. Read next token from the file and return it as a string.
  1141.  
  1142. Arguments:
  1143.     breakString     String of "break" characters (after token)
  1144.     skipString      String of characters to skip (before token)
  1145.     xtbl            Callback proc table
  1146.     hFile           LxMemHandle to object instance
  1147. ------------------------------------------------------------------------------
  1148. */
  1149.  
  1150. long __far __pascal __export _FileIO_mReadToken(
  1151.     LxMemHandle breakString, LxMemHandle skipString, 
  1152.     LxProcTablePtr xtbl, LxMemHandle hFile)
  1153. {
  1154.     pFileIO     pFile;
  1155.     LPSTR       breakPtr;
  1156.     LPSTR       skipPtr;
  1157.     LxMemHandle hdl;
  1158.         
  1159.     lFileIOError = FILEIOE_SUCCESS;
  1160.         
  1161.     pFile = xtbl->mem_Lock( hFile);
  1162.     breakPtr = xtbl->mem_Lock( breakString );
  1163.     skipPtr = xtbl->mem_Lock( skipString );
  1164.         
  1165.     hdl = SkipReadBreak( pFile->sFileID, breakPtr, skipPtr, xtbl );
  1166.         
  1167.     xtbl->mem_Unlock( breakString );
  1168.     xtbl->mem_Unlock( skipString );
  1169.     xtbl->mem_Unlock( hFile);
  1170.     return (long)hdl;
  1171. }
  1172.  
  1173. /*
  1174. ------------------------------------------------------------------------------
  1175. FUNCTION        ||      _FileIO_mSetFinderInfo
  1176.  
  1177. Set the "finder" info attrributes of a file.  This is MAC specific.
  1178.  
  1179. Arguments:
  1180.     xtbl            Callback proc table
  1181.     hFile           LxMemHandle to object instance
  1182. ------------------------------------------------------------------------------
  1183. */
  1184.  
  1185. long __far __pascal __export _FileIO_mSetFinderInfo(
  1186.     LxMemHandle typeString, LxMemHandle creatorString, 
  1187.     LxProcTablePtr xtbl, LxMemHandle hFile)
  1188. {
  1189.     // Null implementation.
  1190.     return -1;
  1191. }
  1192.  
  1193.  
  1194.  
  1195. /*
  1196. ------------------------------------------------------------------------------
  1197. FUNCTION        ||      _FileIO_mGetFinderInfo
  1198.  
  1199. Get the "finder" info attrributes of a file.  This is MAC specific.
  1200.  
  1201. Arguments:
  1202.     xtbl            Callback proc table
  1203.     hFile           LxMemHandle to object instance
  1204. ------------------------------------------------------------------------------
  1205. */
  1206.  
  1207. long __far __pascal __export _FileIO_mGetFinderInfo(
  1208.     LxProcTablePtr xtbl, LxMemHandle hFile)
  1209. {
  1210.     // Null implementation.
  1211.     return (long) xtbl->string_New( "" );
  1212. }
  1213.         
  1214.  
  1215. /*
  1216. ------------------------------------------------------------------------------
  1217. FUNCTION        ||      _FileIO_mDelete
  1218.  
  1219. Delete the file and dispose of me.
  1220.  
  1221. Arguments:
  1222.     xtbl            Callback proc table
  1223.     hFile           LxMemHandle to object instance
  1224. ------------------------------------------------------------------------------
  1225. */
  1226.  
  1227. long __far __pascal __export _FileIO_mDelete(
  1228.     LxProcTablePtr xtbl, LxMemHandle hFile)
  1229. {
  1230.     pFileIO     pFile;
  1231.     LPSTR       pFileName;
  1232.         
  1233.     lFileIOError = FILEIOE_SUCCESS;
  1234.     pFile =  xtbl->mem_Lock( hFile);
  1235.  
  1236.     if (_lclose(pFile->sFileID) != 0)
  1237.     {
  1238.         lFileIOError = FILEIOE_FILE_NOT_OPEN;
  1239.     }
  1240.     if (pFile->hFileName != NULL)
  1241.     {
  1242.         pFileName = xtbl->mem_Lock( pFile->hFileName);
  1243.         remove( pFileName );
  1244.         xtbl->mem_Unlock( pFile->hFileName );
  1245.                 
  1246.         xtbl->mem_Dispose(pFile->hFileName);
  1247.     }
  1248.     xtbl->mem_Unlock( hFile);
  1249.     xtbl->xobj_Dispose( hFile );
  1250.         
  1251.     return 0;
  1252. }
  1253.  
  1254. /* ------------------------------------------------------------------------ */
  1255. // Swap the bytes of a short
  1256. short  mem_XShort(short x)
  1257. {
  1258.     register unsigned char temp;
  1259.     union
  1260.     {
  1261.         short oneWord;
  1262.         unsigned char twoBytes[2];
  1263.     } Moto;
  1264.     Moto.oneWord = x;
  1265.     /* swap two end bytes */
  1266.     temp = Moto.twoBytes[1];
  1267.     Moto.twoBytes[1] = Moto.twoBytes[0];
  1268.     Moto.twoBytes[0] = temp;
  1269.     return (Moto.oneWord);
  1270. }
  1271.         
  1272. /*
  1273. ------------------------------------------------------------------------------
  1274. FUNCTION        ||      _FileIO_mReadPICT
  1275.  
  1276. Arguments:
  1277.     nargs           Number of arguments. Should be zero (0)
  1278.     argp            Array of arguments.  argp[0] used to return value
  1279.     xtbl            Callback proc table
  1280.     hFile           LxMemHandle to object instance
  1281. ------------------------------------------------------------------------------
  1282. */
  1283.  
  1284. long __far __pascal __export _FileIO_mReadPICT(
  1285.     long nargs, LxValuePtr argp, LxProcTablePtr xtbl, LxMemHandle hFile)
  1286. {
  1287.     pFileIO     pFile;
  1288.     LxMemHandle pictHdl = 0;
  1289.     long        len;
  1290.     char _huge *pictPtr;
  1291.         UINT                cbRead;
  1292.         unsigned char *cp;
  1293. #define MAX_LREAD_BYTES    ((long)(0xFFFE))
  1294.  
  1295.     lFileIOError = FILEIOE_SUCCESS;
  1296.     pFile = xtbl->mem_Lock( hFile);
  1297.  
  1298.     if (pFile->sFileID == -1)
  1299.             goto errorReturn;
  1300.  
  1301.         len = _FileIO_mGetLength( xtbl, hFile);
  1302.         if (lFileIOError != FILEIOE_SUCCESS)
  1303.             goto errorReturn;
  1304.         
  1305.         len = len - 512;
  1306.         if (len < 0)
  1307.             goto errorReturn;
  1308.         
  1309.         _FileIO_mSetPosition( (long)512, xtbl, hFile);
  1310.         if (lFileIOError != FILEIOE_SUCCESS)
  1311.             goto errorReturn;
  1312.  
  1313.     pictHdl = xtbl->mem_New( len, FALSE);
  1314.     if (! pictHdl)
  1315.         goto errorReturn;
  1316.                 
  1317.         pictPtr = xtbl->mem_Lock( pictHdl );
  1318.         do {
  1319.             cbRead = _lread(pFile->sFileID, pictPtr, MAX_LREAD_BYTES);
  1320.             len -= cbRead;
  1321.             pictPtr += cbRead;
  1322.         } while (len > 0 && cbRead > 0);
  1323.  
  1324.     xtbl->mem_Unlock( pictHdl);
  1325.         
  1326. #define VERSION_OFFSET 10    // offset to version opcode in the picture data
  1327.         cp = (unsigned char *)*pictHdl + VERSION_OFFSET;
  1328.         
  1329.         if (! ((cp[0] == 0x11 && cp[1] == 0x01) ||
  1330.                  (cp[0] == 0x00 && cp[1] == 0x11 && cp[2] == 0x02 && cp[3] == 0xff)) )
  1331.         {
  1332.                 // Wrong format.
  1333.                 goto errorReturn;
  1334.         }
  1335.         // Correct byte order of first 5 short. Len word and rect frame.
  1336.         xtbl->mem_ReverseBytes( *pictHdl, "2", 2/*entrySize*/, 5*2/*len*/);
  1337.         
  1338.         // Successful return.
  1339.         // Fill in the return value
  1340.         argp[0].ty = TY_PICTURE;
  1341.         argp[0].it = (long)pictHdl;
  1342.     goto home;
  1343.         
  1344. errorReturn:
  1345.     // Bad news. Clean up and go home.
  1346.     if (pictHdl)
  1347.         xtbl->mem_Dispose( pictHdl );
  1348.                 
  1349. home:
  1350.     xtbl->mem_Unlock( hFile);
  1351.     return 0;
  1352.  }
  1353.  
  1354.  
  1355. /*
  1356. ------------------------------------------------------------------------------
  1357. FUNCTION        ||      _FileIO_SetOverrideDrive
  1358.  
  1359. Set override drive to use when loading linked castmembers.
  1360. Returns old override drive setting.
  1361.  
  1362. Arguments:
  1363.     driverLetter    Character to code of new driver override letter or 0 to clear
  1364. ------------------------------------------------------------------------------
  1365. */
  1366.  
  1367. long __far __pascal __export _FileIO_mSetOverrideDrive(
  1368.     long driverLetter, LxProcTablePtr xtbl, LxMemHandle hFile)
  1369. {
  1370.     return xtbl->SetOverrideDrive( (char)driverLetter);
  1371. }
  1372.  
  1373.  
  1374.